package org.hackystat.ui.telemetryviewer.gwt.client;

import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * The container for the JUnit chart, it encapsulates all internals into one easy managable widget.
 *
 * @author Pavel Senin.
 *
 */
public class ChartJUnit
    extends ChartWidget {

  /* the chart image holder */
  final ChartImageWidget chartImage;

  /* the initial span */
  String timeSpan = "7d";

  /* delimeter to use in queries */
  static final char delimiter = '#';

  /* label widget used for request debugging */
  static final Label label = new Label("clientRequest");

  /* label widget used for response debugging */
  static final Label label2 = new Label("serverResponse");

  /* label style used for debug labels */
  static final String trickyStyleName = "chart-SpanWidget";

  /**
   * Creates an instance and reports a handler.
   *
   * @return the widget handler.
   */
  public static ChartHandler init() {
    return new ChartHandler("JUnit", "JUnit tests analysis") {
      public ChartWidget createInstance() {
        return new ChartJUnit();
      }
    };
  }

  /**
   * Creates the object and initializes all of the internal widgets.
   *
   */
  public ChartJUnit() {

    /* instantiating the description widget */
    HTML description = new HTML("How do you write testing code? <br> The simplest way is "
        + "as an expression in a debugger. You can change debug expressions without "
        + "recompiling,and you can wait to decide what to write until you have seen the "
        + "running objects. You can also write test expressions as statements which print "
        + "to the standard output stream. <br> Both styles of tests are limited because "
        + "they require human judgment to analyze their results. Also, they don't compose "
        + "nicely - you can only execute one debug expression at a time and a program with "
        + "too many print statements causes the dreaded \"Scroll Blindness\" . <br> <strong> JUnit"
        + " tests do not require human judgment to interpret, and it is easy to run many of them"
        + " at the same time.</strong>", true);
    description.setStyleName("chart-InfoWidget");

    /* instantiating span selection widget */
    final SpanRangeWidget spanRange = new SpanRangeWidget(this);
    loadSpans(spanRange);

    /* instantiating chart widget */
    chartImage = new ChartImageWidget("junit#7d");
    chartImage.setStyleName("chart-Image");

    /* adding info and chart widgets to the root panel */
    VerticalPanel mainLayoutPanel = new VerticalPanel();
    mainLayoutPanel.setVerticalAlignment(VerticalPanel.ALIGN_TOP);
    mainLayoutPanel.setSpacing(0);
    mainLayoutPanel.setStyleName("chart-DependencyPanel");

    // add description
    mainLayoutPanel.add(description);

    VerticalPanel allWidgetsPanel = new VerticalPanel();
    allWidgetsPanel.setStyleName(trickyStyleName);

    // add the span menu
    HorizontalPanel hpSpan = new HorizontalPanel();
    hpSpan.add(spanRange);
    hpSpan.setStyleName(trickyStyleName);
    allWidgetsPanel.add(hpSpan);

    // add the chart widget
    HorizontalPanel hpChart = new HorizontalPanel();
    hpChart.add(chartImage);
    hpChart.setStyleName(trickyStyleName);
    allWidgetsPanel.add(hpChart);

    // add the dummy debugG
    label.setStyleName("dummyDebugLabel");
    label.setText("clientRequest: \"junit#7d\"");
    HorizontalPanel hpDebugLabel = new HorizontalPanel();
    hpDebugLabel.add(label);
    hpDebugLabel.setStyleName(trickyStyleName);

    allWidgetsPanel.add(hpDebugLabel);

    // add the dummy debugG #2
    label2.setStyleName("dummyDebugLabel");
    label2.setText("serverResponse:");
    HorizontalPanel hpDebugLabel2 = new HorizontalPanel();
    hpDebugLabel2.add(label2);
    hpDebugLabel2.setStyleName(trickyStyleName);

    allWidgetsPanel.add(hpDebugLabel2);

    mainLayoutPanel.add(allWidgetsPanel);

    initWidget(mainLayoutPanel);

  }

  /**
   * Adds all the available spans into the Spans panel.
   *
   * @param spanRange the list widget which would hold all added spans.
   */
  private void loadSpans(SpanRangeWidget spanRange) {

    SpanButton spb = new SpanButton("7d");
    spb.addClickListener(spanRange);
    spanRange.addSpan(spb);

    spb = new SpanButton("14d");
    spb.addClickListener(spanRange);
    spanRange.addSpan(spb);

    spb = new SpanButton("1m");
    spb.addClickListener(spanRange);
    spanRange.addSpan(spb);

    spb = new SpanButton("3m");
    spb.addClickListener(spanRange);
    spanRange.addSpan(spb);

    spb = new SpanButton("6m");
    spb.addClickListener(spanRange);
    spanRange.addSpan(spb);

    spb = new SpanButton("1y");
    spb.addClickListener(spanRange);
    spanRange.addSpan(spb);
  }

  /**
   * Update chart image when needed.
   *
   * @param span the chart parameters name.
   * @param series the optional parameters string.
   */
  public void updateChart(String span, String series) {

    // the case when span is not null
    if (null == span) {
      this.updateChartImage();
    }
    else {
      // the case when span is not null
      this.timeSpan = span;
      this.updateChartImage();
    }
  }

  /**
   * Makes a server request for the image by composes the request string and sending it through
   * asynchronous RPC call.
   *
   */
  private void updateChartImage() {

    final String request = "junit" + ChartJUnit.delimiter + this.timeSpan;

    chartImage.update(request);
    ChartJUnit.label.setText("Client request: \"" + request + "\"");

    ChartJUnit.label2.setText("Server response: \"" + chartImage.getLatestResponse() + "\"");
  }

  /** {@inheritDoc} */
  public void setSpan(String spn) {
    this.timeSpan = spn;
    updateChartImage();
  }
}
